/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/cat.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../helper_pass_through/head.h"
#include "../data_struct/head.h"
#include "../config/head.h"
#include "../macro/head.h"
#include "../impl/head.h"
#include "../impl/head.h"
#include "../msg/head.h"
#include "helper_thread_dispatcher.h"

namespace cat
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static xos::i_callback * packet_thread_ptr = 0;
    static xos::i_callback * net_thread_ptr = 0;
    static xos::i_list * fast_job_list_ptr = 0;
    static xos::i_list * slow_job_list_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    helper_thread_dispatcher::helper_thread_dispatcher()
    {
    }

    helper_thread_dispatcher::~helper_thread_dispatcher()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    xos::i_callback * helper_thread_dispatcher::get_thread( bool bSlowJob )
    {
        xos::i_callback * pThread = 0;
        xos::i_list * pThreadList = 0;
        int nMaxThreadNum = 0;

        {
            if( !bSlowJob )
            {
                nMaxThreadNum = config::get()->max_fast_job_thread_num;
                pThreadList = fast_job_list_ptr;
            }
            else
            {
                nMaxThreadNum = config::get()->max_slow_job_thread_num;
                pThreadList = slow_job_list_ptr;
            }
        }

        for( pThreadList->reset(); pThreadList->data(); pThreadList->next() )
        {
            xos::i_callback * pT = ( xos::i_callback* )pThreadList->data();
            if( !pThread )
            {
                pThread = pT;
            }
            else if( pThread->size() > pT->size() )
            {
                pThread = pT;
            }
        }

        if( !pThread || ( ( pThread->size() > 5 ) && ( pThreadList->size() < nMaxThreadNum ) ) )
        {
            pThread = 0;
            mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_CALLBACK, ( void** )&pThread );
            helper_pass_through::add_thread( pThread );
            pThreadList->push_back( pThread );
        }

        return pThread;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_thread_dispatcher::dispatch( xos::i_msg *& pMsg )
    {
        int ret = 1;

        int nThreadType = msg::get_thread_type( pMsg );
        bool bSlowJob = msg::get_slow( pMsg );
        xos::i_callback * pThread = 0;
        
        switch( nThreadType )
        {
        case THREAD_TYPE_WORKER:
            {
                pThread = get_thread( bSlowJob );
            }
            break;
        case THREAD_TYPE_PACKET:
            {
                pThread = packet_thread();
            }
            break;
        case THREAD_TYPE_NET:
            {
                pThread = net_thread();
            }
            break;
        default:
            {
                ret = 0;
            }
            break;
        }

        if( pThread )
        {
            pThread->notify( pMsg );
            pThread = 0;
        }
        
        return ret;
    }

    xos::i_callback * helper_thread_dispatcher::packet_thread()
    {
        xos::i_callback * pRet = packet_thread_ptr;
        if( !pRet )
        {
            mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_CALLBACK, ( void** )&pRet );
            helper_pass_through::add_thread( pRet );
            packet_thread_ptr = pRet;
        }
        return pRet;
    }

    xos::i_callback * helper_thread_dispatcher::net_thread()
    {
        xos::i_callback * pRet = net_thread_ptr;
        if( !pRet )
        {
            mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_CALLBACK, ( void** )&pRet );
            helper_pass_through::add_thread( pRet );
            net_thread_ptr = pRet;
        }
        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int helper_thread_dispatcher::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_LIST, ( void** )&fast_job_list_ptr );
        }

        if( 0 == ret )
        {
            ret = mgr::xos()->xos()->create( xos::i_xos::XOS_OBJ_LIST, ( void** )&slow_job_list_ptr );
        }

        if( ( 0 == ret ) && ( 0 == config::get()->max_fast_job_thread_num ) )
        {
            int num = mgr::xos()->misc()->get_cpu_num();
            if( 0 == num )
            {
                num = 1;
            }
            config::get()->max_fast_job_thread_num = num;
        }

        return ret;
    }

    int helper_thread_dispatcher::term()
    {
        int ret = 0;

        xos_stl::release_interface( fast_job_list_ptr );
        xos_stl::release_interface( slow_job_list_ptr );
        xos_stl::release_interface( packet_thread_ptr );
        xos_stl::release_interface( net_thread_ptr );

        return ret;
    }

} // cat
